
package com.rrd.dw.azkaban.flow;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Edge {
    private final String sourceId;
    private final String targetId;
    private Node source;
    private Node target;
    private String error;

    // Useful in rendering. 
    private String guideType;
    private List<Point2D> guideValues;

    public Edge(String fromId, String toId) {
        this.sourceId = fromId;
        this.targetId = toId;
    }

    public Edge(Edge clone) {
        this.sourceId = clone.getSourceId();
        this.targetId = clone.getTargetId();
        this.error = clone.getError();
    }

    public String getId() {
        return this.getSourceId() + ">>" + this.getTargetId();
    }

    public String getSourceId() {
        return this.sourceId;
    }

    public String getTargetId() {
        return this.targetId;
    }

    public void setError(String error) {
        this.error = error;
    }

    public String getError() {
        return this.error;
    }

    public boolean hasError() {
        return this.error != null;
    }

    public Node getSource() {
        return this.source;
    }

    public void setSource(Node source) {
        this.source = source;
    }

    public Node getTarget() {
        return this.target;
    }

    public void setTarget(Node target) {
        this.target = target;
    }

    public String getGuideType() {
        return this.guideType;
    }

    public List<Point2D> getGuideValues() {
        return this.guideValues;
    }

    public void setGuides(String type, List<Point2D> values) {
        this.guideType = type;
        this.guideValues = values;
    }

    public Object toObject() {
        HashMap<String, Object> obj = new HashMap<>();
        obj.put("source", this.getSourceId());
        obj.put("target", this.getTargetId());
        if (this.hasError()) {
            obj.put("error", this.error);
        }
        if (this.guideValues != null) {
            HashMap<String, Object> lineGuidesObj = new HashMap<>();
            lineGuidesObj.put("type", this.guideType);

            ArrayList<Object> guides = new ArrayList<>();
            for (Point2D point : this.guideValues) {
                HashMap<String, Double> pointObj = new HashMap<>();
                pointObj.put("x", point.getX());
                pointObj.put("y", point.getY());
                guides.add(pointObj);
            }
            lineGuidesObj.put("values", guides);

            obj.put("guides", lineGuidesObj);
        }

        return obj;
    }

    @SuppressWarnings("unchecked")
    public static Edge fromObject(Object obj) {
        HashMap<String, Object> edgeObj = (HashMap<String, Object>) obj;

        String source = (String) edgeObj.get("source");
        String target = (String) edgeObj.get("target");

        String error = (String) edgeObj.get("error");

        Edge edge = new Edge(source, target);
        edge.setError(error);

        if (edgeObj.containsKey("guides")) {
            Map<String, Object> guideMap = (Map<String, Object>) edgeObj
                .get("guides");
            List<Object> values = (List<Object>) guideMap.get("values");
            String type = (String) guideMap.get("type");

            ArrayList<Point2D> valuePoints = new ArrayList<>();
            for (Object pointObj : values) {
                Map<String, Double> point = (Map<String, Double>) pointObj;

                Double x = point.get("x");
                Double y = point.get("y");

                valuePoints.add(new Point2D.Double(x, y));
            }

            edge.setGuides(type, valuePoints);
        }

        return edge;
    }

}
